package com.jingjiu.homeservicesbiz.cos;

import com.jingjiu.homeservicesapi.enums.ResultEnum;
import com.jingjiu.homeservicesbiz.exception.OlinkBaseException;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.http.HttpProtocol;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.model.UploadResult;
import com.qcloud.cos.region.Region;
import com.qcloud.cos.transfer.TransferManager;
import com.qcloud.cos.transfer.Upload;
import jakarta.annotation.Resource;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.tika.Tika;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Slf4j
@Service
public class UploadService {

	@Resource
	private COSConfig cosConfig;


	private COSClient createCOSClient() {
		COSCredentials cosCredentials = new BasicCOSCredentials(cosConfig.getSecretId(), cosConfig.getSecretKey());
		ClientConfig clientConfig = new ClientConfig(new Region(cosConfig.getRegionName()));
		return new COSClient(cosCredentials, clientConfig);
	}

	/**
	 * 创建传输管理器
	 *
	 * @return {@link TransferManager }
	 */
	private TransferManager createTransferManager() {
		// 1 初始化用户身份信息(secretId, secretKey)
		// 1 初始化用户身份信息（secretId, secretKey）。
		String secretId = cosConfig.getSecretId();
		String secretKey = cosConfig.getSecretKey();
		String region = cosConfig.getRegionName();
		COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
		ClientConfig clientConfig = new ClientConfig(new Region(region));
		clientConfig.setHttpProtocol(HttpProtocol.https);
		// 3 生成cos客户端
		COSClient cosclient = new COSClient(cred, clientConfig);

		ExecutorService threadPool = Executors.newFixedThreadPool(32);
		// 传入一个threadpool, 若不传入线程池, 默认TransferManager中会生成一个单线程的线程池。
		return new TransferManager(cosclient, threadPool);
	}


	/**
	 * 上传档案
	 */

	@SneakyThrows
	public String upload(InputStream inputStream, String path) {

		String extractFileName = extractFileName(path);


		TransferManager transferManager = createTransferManager();
		String key = "cdn/" + extractFileName;
		// bucket名需包含appid
		String bucketName = cosConfig.getBucketName();

		ObjectMetadata objectMetadata = new ObjectMetadata();

		int available = inputStream.available();
		objectMetadata.setContentLength(available);


		PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key, inputStream, objectMetadata);
		try {
			// 返回一个异步结果Upload, 可同步的调用waitForUploadResult等待upload结束, 成功返回UploadResult, 失败抛出异常.
			long startTime = System.currentTimeMillis();
			Upload upload = transferManager.upload(putObjectRequest);
//            showTransferProgress(upload);
			UploadResult uploadResult = upload.waitForUploadResult();
			long endTime = System.currentTimeMillis();

			log.info("文件 {} 上传耗时: {} 秒", extractFileName, (endTime - startTime) / 1000);

		} catch (Exception e) {
			log.error("文件上传接口异常", e);
			throw new OlinkBaseException(ResultEnum.FILE_UPLOAD_FAIL);
		} finally {
			inputStream.close();
		}

		transferManager.shutdownNow();

		return cosConfig.getBaseUrl() + "/" + key;
	}

	private String getFileType(InputStream inputStream) {
		try {
			return new Tika().detect(inputStream);
		} catch (IOException e) {
			log.error("Failed to detect file type", e);
			return null;
		}
	}

	public String upload(File file, String roomName, boolean isDel) {
		COSClient cosClient = createCOSClient();
		String key = "/" + roomName + "/" + file.getName();

		try {
			PutObjectRequest putObjectRequest = new PutObjectRequest(cosConfig.getBucketName(), key, file);
			cosClient.putObject(putObjectRequest);
			if (isDel) {
				boolean deleted = file.delete();
				if (!deleted) {
					log.warn("Failed to delete file: {}", file.getName());
				}
			}
		} catch (IllegalStateException e) {
			log.error("IllegalStateException occurred", e);
		} finally {
			cosClient.shutdown();
		}

		return getFileUrl(file.getName(), roomName);
	}

	private String getFileUrl(String fileName, String roomName) {
		return cosConfig.getBaseUrl() + roomName + "/" + fileName;
	}

	private String extractFileName(String filePath) {
		if (filePath == null || !filePath.contains("/")) {
			return filePath;
		}
		return filePath.substring(filePath.lastIndexOf('/') + 1);
	}
}